﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using Assets.Script.Config;

public class HBDataCenter :Singleton<HBDataCenter>
{
    //-----------------英雄战相关----------------

    List<HeroVo> m_lisHeros;

    /// <summary>
    /// 输入编辑器数据  返回英雄战斗需要的信息
    /// </summary>
    /// <param name="heros">英雄信息</param>
    /// <param name="nodes">行为节点</param>
    public void Editor2Fight(List<HeroVo> heros,List<Action_Attack> attack,List<Action_DoBuffer> buf,
                             List<Action_Sing> sing,Dictionary<int,Action_Attack> fanji,List<ActionNode> m_All)
    {
        Dictionary<int, ActionNode> m_dicNodes = new Dictionary<int, ActionNode>();
        for (int i = 0; i < attack.Count; i++)
        {
            m_dicNodes.Add(attack[i].Index, attack[i]);
        }
        for (int i = 0; i < buf.Count; i++)
        {
            m_dicNodes.Add(buf[i].Index, buf[i]);
        }
        for (int i = 0; i < sing.Count; i++)
        {
            m_dicNodes.Add(sing[i].Index, sing[i]);
        }
        m_All.Clear();
        int index_X = 0;
        for (int i = 0; i < (m_dicNodes.Count); i++)
        {
            if (m_dicNodes.ContainsKey(i))
            {
                m_dicNodes[i].Index = index_X;
                index_X++;
                if (m_dicNodes[i].GetType() == typeof(Action_Attack))
                {
                    Action_Attack _attack = m_dicNodes[i] as Action_Attack;
                    _attack.Init();
                    m_All.Add(ConvertChild(_attack));
                    for (int j = 0; j < _attack.m_lisDefs.Count; j++)
                    {
                        if (fanji.ContainsKey(_attack.m_lisDefs[j].counterNodeId))
                        {
                            fanji[_attack.m_lisDefs[j].counterNodeId].Index = index_X;
                            index_X++;
                            fanji[_attack.m_lisDefs[j].counterNodeId].Init();
                            m_All.Add(ConvertChild(fanji[_attack.m_lisDefs[j].counterNodeId]));
                        }
                    }
                }
                else
                {
                    m_All.Add(m_dicNodes[i]);
                    if (m_dicNodes[i].GetType() == typeof(Action_Sing))
                    {
                        ((Action_Sing)m_dicNodes[i]).Init();
                    }
                    else if (m_dicNodes[i].GetType() == typeof(Action_DoBuffer))
                    {
                        ((Action_DoBuffer)m_dicNodes[i]).Init();
                    }
                }
            }
            else
            {
                Debug.Log("Key not have index: " + i);
            }
        }
        for (int i = 0; i < heros.Count; i++)
        {
            heros[i].Init(HeroBattleStage.BattleBigType.Hero);
        }
        m_All.Sort();
    }

    /// <summary>
    /// 输入战报的数据 返回英雄战斗需要的2个list信息
    /// </summary>
    /// <param name="heros"></param>
    /// <param name="nodes"></param>
    public void Report2Fight(List<HeroVo> heros,List<ActionNode> nodes,ReportDetail report,bool _lisLeft)
    {
        //先只考虑一场英雄战的情况
        if(report != null)
        {
            m_lisHeros = new List<HeroVo>();
            for (int i = 0; i < report.force_info.Count; i++)
            {
                ReportForce force = report.force_info[i];
                //Debug.Log("Force.pos:  "+force.pos);
                if (force.protoId != 0)
                {
                    HeroVo heroVo = new HeroVo();
                    heroVo.index = force.pos - 1;
                    heroVo.reportId = heroVo.index;
                    heroVo.pId = force.protoId;
                    Debug.Log("英雄模板ID: " + force.protoId);
                    heroVo.initHp = force.bingliBeforeFight;
                    heroVo.m_bFilp = force.pos > SlgFightDef.c_iHeroIndexStep;
                    heroVo.Init(HeroBattleStage.BattleBigType.Hero);
                    heros.Add(heroVo);
                }
            }
            m_lisHeros = heros;

            ConvertActionNode(nodes, report.fight_info,(int)HeroBattleStage.BattleBigType.Hero);
        }
    }

    public void ConvertActionNode(List<ActionNode> nodes, List<oneFightInfoD> oneFightInfos,int battleBigType)
    {
        long ready_Action = 100;    //记录收到1000 的对象
        int nowRound = 0;           //记录当前回合数

        List<ActionNode> m_lisActions = new List<ActionNode>();

        Action_Attack AtkNode = null;
        Action_Sing SingNode = null;
        Action_DoBuffer DoBuffer = null;

        bool m_bJianShe = false;
        bool m_bBaoHu = false;
        int m_iBaoHu_YuanID = 0;
        bool m_bFanJi = false;

        int m_iDefId = 99;
        int nodeIndex = 0;
        bool m_bReadyState = true;


        for (int i = 0; i < oneFightInfos.Count; i++)
        {
            oneFightInfoD oneAction = oneFightInfos[i];
            Dmg _dmg;
            BufDmg _bufDmg;
            switch (oneAction.action)
            {
                case 17://准备回合
                    m_bReadyState = true;
                    break;
                case 18://第$1回合[-]
                    m_bReadyState = false;
                    nowRound = (int)oneAction.values[0];
                    break;
                case 20://{$1:hero}发动【{$2:skill}】                            技能的开始
                    if (m_bJianShe)
                    {
                        m_bJianShe = false;
                    }
                    else
                    {
                        if (AtkNode != null)
                        {
                            m_lisActions.Add(AtkNode);
                            nodeIndex++;
                        }
                        GetAttackTypeBySkill(ref AtkNode, (int)oneAction.values[1]);
                        AtkNode.m_bBefore = m_bReadyState;
                        AtkNode.Index = nodeIndex;
                        AtkNode.attackId = (int)oneAction.values[0] - 1;
                        if (m_bFanJi)
                        {
                            m_bFanJi = false;
                            AtkNode.m_bCounter = true;
                        }
                    }
                    break;
                case 21://{$1:hero}对{$2:hero}发动普通攻击[-]                    普攻的开始
                    if (m_bJianShe)
                    {
                        m_bJianShe = false;
                    }
                    else
                    {
                        if (AtkNode != null)
                        {
                            m_lisActions.Add(AtkNode);
                            nodeIndex++;
                        }
                        GetAttackTypeByHeroPid(ref AtkNode, GetHeroPIDByIndex((int)oneAction.values[0] - 1));
                        AtkNode.m_bBefore = m_bReadyState;
                        AtkNode.Index = nodeIndex;
                        AtkNode.attackId = (int)oneAction.values[0] - 1;
                        if (m_bFanJi)
                        {
                            m_bFanJi = false;
                            AtkNode.m_bCounter = true;
                        }
                    }
                    break;
                case 22://{$1:hero}损失了[f1c74a]{$2:value}[-]兵力({$3:value})   通用扣血
                        //Dmg normalDmg = GetDmgByDefId(AtkNode, (int)oneAction.values[0]);
                    m_iDefId = (int)oneAction.values[0] - 1;
                    _dmg = GetDmgByDefId(AtkNode, m_bBaoHu ? m_iBaoHu_YuanID : m_iDefId);
                    _dmg.dmg = -(int)oneAction.values[1];
                    _dmg.isCri = false;
                    if (m_bBaoHu)
                    {
                        _dmg.protectId = m_iDefId;
                        m_bBaoHu = false;
                    }
                    break;
                case 23://{$1:hero}回复了[f1c74a]{$2:value}[-]兵力({$3:value})            通用加血
                    m_iDefId = (int)oneAction.values[0] - 1;
                    _dmg = GetDmgByDefId(AtkNode, m_iDefId);
                    _dmg.dmg = (int)oneAction.values[1];
                    _dmg.isCri = false;

                    break;
                case 24://27和这个一样根本没用到   {$1:hero}的{$2:skillEff}了[f1c74a]{$3:value}[-] ({$4:value})  1.英雄 2.skillEffId生效 3.变化值 4.哪个属性
                        //Dmg bufDmg = GetDmgByDefId(AtkNode, (int)oneAction.values[0]);
                    _dmg = GetDmgByDefId(AtkNode, (int)oneAction.values[0] - 1);
                    GetBufDataInDmg(_dmg, (int)oneAction.values[1]);
                    break;
                case 44://{$1:hero}由于{$2:hero}【{$3:skill}】施加的{$4:skillEff}效果损失了[f1c74a]{$5:value}[-]兵力({$6:value})
                        //要把正在处理的 Atk塞进去
                    if (AtkNode != null)
                    {
                        m_lisActions.Add(AtkNode);
                        nodeIndex++;
                        AtkNode = null;
                    }
                    DoBuffer = new Action_DoBuffer();
                    DoBuffer.attackId = (int)oneAction.values[1] - 1;
                    _bufDmg = GetBufDmg(DoBuffer, (int)oneAction.values[3]);
                    _bufDmg.dmg = -(int)oneAction.values[4];
                    DoBuffer.Index = nodeIndex;
                    m_lisActions.Add(DoBuffer);
                    nodeIndex++;
                    Debug.LogFormat("NodeIndex:  {0} -2", DoBuffer.Index);

                    break;
                case 45://{$1:hero}【{$2:skill}】的{$3:skillEff}效果为{$4:hero}回复了-(font color='#f1c74a')-{$5:value}-(/font)-兵力({$6:value})
                        //要把正在处理的 Atk塞进去
                    if (AtkNode != null)
                    {
                        m_lisActions.Add(AtkNode);
                        nodeIndex++;
                        AtkNode = null;
                    }
                    DoBuffer = new Action_DoBuffer();
                    DoBuffer.attackId = (int)oneAction.values[3] - 1;
                    _bufDmg = GetBufDmg(DoBuffer, (int)oneAction.values[2]);
                    _bufDmg.dmg = (int)oneAction.values[4];
                    DoBuffer.Index = nodeIndex;
                    m_lisActions.Add(DoBuffer);
                    nodeIndex++;
                    Debug.LogFormat("NodeIndex:  {0} -2", DoBuffer.Index);

                    break;
                case 48://{$1:hero}已存在{$2:skillEff}效果
                    _dmg = GetDmgByDefId(AtkNode, (int)oneAction.values[0] - 1);
                    GetBufDataInDmg(_dmg, (int)oneAction.values[1]);
                    break;
                case 51://{$1:hero}的技能{$2:skill}开始准备！
                        //要把正在处理的 Atk塞进去
                    if (AtkNode != null)
                    {
                        m_lisActions.Add(AtkNode);
                        nodeIndex++;
                        AtkNode = null;
                    }

                    SingNode = new Action_Sing();
                    SingNode.attackId = (int)oneAction.values[0] - 1;
                    SingNode.skillActionId = GetSkillActionId_BySkillPid((int)oneAction.values[1]);
                    SingNode.Index = nodeIndex;
                    m_lisActions.Add(SingNode);
                    nodeIndex++;
                    Debug.LogFormat("NodeIndex:  {0} -1", SingNode.Index);

                    break;
                case 53://{$1:hero}执行溅射
                    m_bJianShe = true;
                    break;
                case 58://{$1:hero}由于被守护，攻击转移.
                    m_bBaoHu = true;
                    m_iBaoHu_YuanID = (int)oneAction.values[0] - 1;
                    break;
                case 60://{$1:hero}由于处于庇护状态，伤害无效
                    m_iDefId = (int)oneAction.values[0] - 1;
                    _dmg = GetDmgByDefId(AtkNode, m_bBaoHu ? m_iBaoHu_YuanID : m_iDefId);
                    _dmg.dmg = 0;
                    _dmg.isCri = false;
                    _dmg.isGod = true;
                    if (m_bBaoHu)
                    {
                        _dmg.protectId = m_iDefId;
                        m_bBaoHu = false;
                    }
                    break;
                case 71://{$1:hero}进行反击
                    m_bFanJi = true;
                    //拿到上一个attackNode
                    if (AtkNode != null)
                    {
                        AtkNode.m_bComeBack = false;
                    }
                    else
                    {
                        Debug.Log("AtkNode==null,不能进行反击");
                    }
                    break;
                case 84://该次攻击造成了暴击，{$1:hero}损失了[f1c74a]{$2:value}[-]兵力({$3:value})  暴击扣血
                    m_iDefId = (int)oneAction.values[0] - 1;
                    _dmg = GetDmgByDefId(AtkNode, m_bBaoHu ? m_iBaoHu_YuanID : m_iDefId);
                    _dmg.dmg = -(int)oneAction.values[1];
                    _dmg.isCri = true;
                    break;
                case 1000:
                    ready_Action = oneAction.values[0];
                    break;
            }
        }

        Debug.Log("Stop");
        nodes.Clear();
        for (int i = 0; i < m_lisActions.Count; i++)
        {
            m_lisActions[i].Init();
            nodes.Add(m_lisActions[i]);
        }
    }

    private Action_Attack ConvertChild(Action_Attack attack)
    {
        if(attack.sActionConfig.actionType == HeroFightDef.c_iActionSkillType_0)
        {
            Action_Attack_Slash slash = new Action_Attack_Slash(attack);
            return slash;
        }
        else if(attack.sActionConfig.actionType == HeroFightDef.c_iActionSkillType_1)
        {
            Action_Attack_Remote remote = new Action_Attack_Remote(attack);
            return remote;
        }
        else if(attack.sActionConfig.actionType == HeroFightDef.c_iActionSkillType_2)
        {
            Action_Attack_Skill skill = new Action_Attack_Skill(attack);
            return skill;
        }
        return null;
    }

    private int GetHeroPIDByIndex(int index)
    {
        for (int i = 0; i < m_lisHeros.Count; i++)
        {
            if(m_lisHeros[i].index == index)
            {
                return m_lisHeros[i].pId;
            }
        }

        return 0;
    }

    private Dmg GetDmgByDefId(Action_Attack attack,int defId)
    {
        if (attack.m_lisDefs == null)
            attack.m_lisDefs = new List<Dmg>();

        Dmg dmg = null;
        for (int i = 0; i < attack.m_lisDefs.Count; i++)
        {
            if(attack.m_lisDefs[i].defId == defId)
            {
                dmg = attack.m_lisDefs[i];
                break;
            }
        }
        if(dmg == null)
        {
            dmg = new Dmg();
            dmg.defId = defId;
            attack.m_lisDefs.Add(dmg);
        }

        return dmg;
    }

    private BufData GetBufDataInDmg(Dmg dmg,int bufPid)
    {
        if (dmg.bufs == null)
            dmg.bufs = new List<BufData>();

        BufData bufData = null;
        for (int i = 0; i < dmg.bufs.Count; i++)
        {
            if(dmg.bufs[i].bufId == bufPid)
            {
                bufData = dmg.bufs[i];
                break;
            }
        }
        if(bufData == null)
        {
            bufData = new BufData();
            bufData.bufId = bufPid;
            dmg.bufs.Add(bufData);
        }

        return bufData;
    }

    private BufDmg GetBufDmg(Action_DoBuffer doBuf,int bufPid)
    {
        if (doBuf.lisBufDmg == null)
            doBuf.lisBufDmg = new List<BufDmg>();

        BufDmg bufDmg = null;
        for (int i = 0; i < doBuf.lisBufDmg.Count; i++)
        {
            if(doBuf.lisBufDmg[i].bufId == bufPid)
            {
                bufDmg = doBuf.lisBufDmg[i];
                break;
            }
        }
        if(bufDmg == null)
        {
            bufDmg = new BufDmg();
            bufDmg.bufId = bufPid;
            doBuf.lisBufDmg.Add(bufDmg);
        }

        return bufDmg;
    }

    private void GetAttackTypeBySkill(ref Action_Attack attack,int skillPid)
    {
        SkillAction sAction = GetSkillActionBySkillPid(skillPid);
        if (sAction != null)
        {
            switch (sAction.actionType)
            {
                case 0:
                    attack = new Action_Attack_Slash();
                    attack.skillActionId = sAction.id;
                    return;
                case 1:
                    attack = new Action_Attack_Remote();
                    attack.skillActionId = sAction.id;
                    return;
                case 2:
                    attack = new Action_Attack_Skill();
                    attack.skillActionId = sAction.id;
                    return;
            }
        }
        attack = null;
    }

    private int GetSkillActionId_BySkillPid(int skillPid)
    {
        SkillAction sAction = GetSkillActionBySkillPid(skillPid);
        if (sAction != null)
            return sAction.id;
        else
            return 0;
    }

    private SkillAction GetSkillActionBySkillPid(int skillPid)
    {
        Skill skill = ConfigManager.Instance.SkillLoader.GetInfoById(skillPid);
        if(skill != null)
        {
            SkillAction sAction = ConfigManager.Instance.skillActionLoader.GetInfoById(skill.skillAction);
            return sAction;
        }
        Debug.Log("Skill is null   " + skillPid);
        return null;
    }

    private void GetAttackTypeByHeroPid(ref Action_Attack attack,int heroPid)
    {
        attack = null;
        UnitBase unitBase = ConfigManager.Instance.unitBaseLoader.GetInfoById(heroPid);
        if(unitBase != null)
        {
            SkillAction sAction = ConfigManager.Instance.skillActionLoader.GetInfoById(unitBase.normalSkillAction);
            if(sAction != null)
            {
                switch(sAction.actionType)
                {
                    case 0:
                        attack = new Action_Attack_Slash();
                        attack.skillActionId = sAction.id;
                        return;
                    case 1:
                        attack = new Action_Attack_Remote();
                        attack.skillActionId = sAction.id;
                        return;
                    case 2:
                        attack = new Action_Attack_Skill();
                        attack.skillActionId = sAction.id;
                        return;
                }
            }
            else
            {
                Debug.Log("skill action is nil   " + unitBase.normalSkillAction);
            }
        }
        else
        {
            Debug.Log("UnitBase is nil   " + heroPid);
            attack = new Action_Attack_Slash();
        }
    }


    //-------------------SLG战斗相关-----------------------
    public void Report2SLG(List<SoldierVo> soldiers,List<HeroVo> heros,List<ActionNode> actions,ReportDetail report)
    {
        if (report != null)
        {
            soldiers.Clear();
            heros.Clear();
            actions.Clear();
            for (int i = 0; i < report.force_info.Count; i++)
            {
                if (report.force_info[i].protoId != 0)
                {
                    int pos = report.force_info[i].pos % 20;
                    if (pos > 3)
                    {
                        SoldierVo vo = new SoldierVo();
                        vo.hp = report.force_info[i].bingliBeforeFight;
                        vo.pId = report.force_info[i].protoId;
                        vo.pos = report.force_info[i].pos;
                        vo.config = ConfigManager.Instance.GetSoliderConfig(vo.pId);
                        vo.beforeHp = report.force_info[i].bingliBeforeFight;
                        vo.afterHp = report.force_info[i].bingliAfterFight;
                        vo.m_bleft = report.force_info[i].pos <= SlgFightDef.c_iHeroIndexStep;
                        soldiers.Add(vo);
                    }
                    else
                    {
                        HeroVo vo = new HeroVo();
                        vo.initHp = report.force_info[i].bingliAfterFight;
                        vo.pId = report.force_info[i].protoId;
                        vo.index = report.force_info[i].pos;
                        vo.m_bFilp = report.force_info[i].pos > SlgFightDef.c_iHeroIndexStep;
                        vo.m_pUnitBase = ConfigManager.Instance.unitBaseLoader.GetInfoById(vo.pId);
                        vo.Init(HeroBattleStage.BattleBigType.Slg);
                        heros.Add(vo);
                    }
                }
            }
            m_lisHeros = heros;
            ConvertActionNode(actions, report.fight_info,(int)HeroBattleStage.BattleBigType.Slg);
        }
    }

    public void Report2Slg_Heros(List<HeroVo> heros,ReportDetail report)
    {
        if (report != null)
        {
            heros.Clear();
            for (int i = 0; i < report.force_info.Count; i++)
            {
                if (report.force_info[i].protoId != 0)
                {
                    if (report.force_info[i].pos <= 6)
                    {
                        //soldiers
                        HeroVo vo = new HeroVo();
                        vo.initHp = report.force_info[i].bingliAfterFight;
                        vo.pId = report.force_info[i].protoId;
                        vo.index = report.force_info[i].pos;
                        vo.m_pUnitBase = ConfigManager.Instance.unitBaseLoader.GetInfoById(vo.pId);
                        vo.Init(HeroBattleStage.BattleBigType.Slg);
                        heros.Add(vo);
                    }
                    else
                    {
                        HeroVo vo = new HeroVo();
                        vo.initHp = report.force_info[i].bingliAfterFight;
                        vo.pId = report.force_info[i].protoId;
                        vo.index = report.force_info[i].pos;
                        vo.m_pUnitBase = ConfigManager.Instance.unitBaseLoader.GetInfoById(vo.pId);
                        vo.Init(HeroBattleStage.BattleBigType.Slg);
                        heros.Add(vo);
                    }
                }
            }
            m_lisHeros = heros;
        }
    }

    public void Report2Slg_Soldiers(List<SoldierVo> soldiers, ReportDetail report)
    {
        if (report != null)
        {
            soldiers.Clear();
            for (int i = 0; i < report.force_info.Count; i++)
            {
                if (report.force_info[i].protoId != 0)
                {
                    if (report.force_info[i].pos <= 6)
                    {
                        SoldierVo vo = new SoldierVo();
                        vo.hp = report.force_info[i].bingliBeforeFight;
                        vo.pId = report.force_info[i].protoId;
                        vo.pos = report.force_info[i].pos;
                        vo.config = ConfigManager.Instance.GetSoliderConfig(vo.pId);
                        vo.beforeHp = report.force_info[i].bingliBeforeFight;
                        vo.afterHp = report.force_info[i].bingliAfterFight;
                        soldiers.Add(vo);
                    }
                    else
                    {
                        //heros
                    }
                }
            }
        }
    }
}

[System.Serializable]
public class HeroVo
{
    public long reportId;
    public int pId;
    public int index;// 0,1,2,3,4,5 站位从左往右
    public int initHp;


    [HideInInspector]
    public string model;
    [HideInInspector]
    public bool m_bFilp = false;
    [HideInInspector]
    public UnitBase m_pUnitBase;

    public HeroVo()
    {

    }

    public HeroVo(int id, int pId, int index, int hp)
    {
        this.reportId = id;
        this.pId = pId;
        this.index = index;
        this.initHp = hp;
    }

    public void Init(HeroBattleStage.BattleBigType battleType)
    {
        //if(battleType == HeroBattleStage.BattleBigType.Hero)
        //{
        //    m_bFilp = (index >= HeroFightDef.c_iMaxHero / 2);
        //}
        //else
        //{
        //    m_bFilp = (index > HeroFightDef.c_iMaxHero / 2);
        //}
        m_pUnitBase = ConfigManager.Instance.unitBaseLoader.GetInfoById(pId);
        model = m_pUnitBase.modelPath;
    }
}

//最基本的数据 A 打 B 
[System.Serializable]
public class Action_Attack : ActionNode, IComparable<Action_Attack>
{
    public bool m_bBefore = false;
    public List<Dmg> m_lisDefs = new List<Dmg>();
    public int skillActionId;//普攻也是技能
    [HideInInspector]
    public SkillAction sActionConfig;
    //如果有反击 那么这个就是 false
    public bool m_bComeBack = true;
    //如果是反击回合 那么这个true
    [HideInInspector]
    public bool m_bCounter = false;

    public override void Init()
    {
        NodeId = Index;
        sActionConfig = ConfigManager.Instance.skillActionLoader.GetInfoById(skillActionId);
        for (int i = 0; i < m_lisDefs.Count; i++)
        {
            if(m_lisDefs[i].counterNodeId != 0)
            {
                m_bComeBack = false;
            }
        }
    }

    public override void ConvertEntityId()
    {
        base.ConvertEntityId();

        for (int i = 0; i < m_lisDefs.Count; i++)
        {
            m_lisDefs[i].defEntityId = HeroBattleMgr.Instance.ConvertReportId2EntityId(m_lisDefs[i].defId);
            m_lisDefs[i].protectEntityId = HeroBattleMgr.Instance.ConvertReportId2EntityId(m_lisDefs[i].protectId);
        }
    }

    public override void EnterNode()
    {
        Debug.LogFormat("行动节点{0}开始   ", Index);
    }

    public override bool NodeError()
    {
        if (BattleEntityFactory.Instance.GetBtEntity(this.attackEntityId) == null)
        {
            Debug.LogFormat("actions:{0}  attackId:{1} 是错的", Index, this.attackEntityId);
            return true;
        }

        if (m_lisDefs.Count == 0)
        {
            Debug.Log("防御方 为空");
            return true;
        }

        for (int i = 0; i < m_lisDefs.Count; i++)
        {
            if (BattleEntityFactory.Instance.GetBtEntity(m_lisDefs[i].defEntityId) == null)
            {
                Debug.LogFormat("actions:{0}  lisDefs: {1}  DefId: {2} 是错的", Index, i, m_lisDefs[i].defId);
                return true;
            }
        }

        //检查 行为是 0用到的配置是不是都有()
        if (sActionConfig.actionType == HeroFightDef.c_iActionSkillType_0 &&
           (sActionConfig.action2 == "0" || sActionConfig.action3 == "0"))
        {
            Debug.LogFormat("攻击行为是 act:{0}_移动过去 停止atk:{1}  ", sActionConfig.action2, sActionConfig.action3);
            return true;
        }

        //检查行为是 1 原地放子弹
        if (sActionConfig.actionType == HeroFightDef.c_iActionSkillType_1 &&
           sActionConfig.action3EffId == 0)
        {
            Debug.LogFormat("射子弹的行为 atkEff:{0} 不能为0,不然射不出去", sActionConfig.action3EffId);
            return true;
        }

        if(ConfigManager.Instance.skillActionLoader.GetInfoById(skillActionId) == null)
        {
            Debug.LogFormat("skillActionId:  {0}  在配置表 skillAction 中没有找到",skillActionId);
            return true;
        }

        return false;
    }

    public override string EditorNodeError()
    {
        string result = "";
        if (m_lisDefs.Count <= 0)
        {
            result += string.Format("    {0}  攻击节点  被攻击单位个数是0", Index);
        }
        if (skillActionId == 0)
        {
            result += string.Format("    skillActionId:{0} 不能为0", this.skillActionId);
        }
        List<int> defIds = new List<int>();
        List<int> protectIds = new List<int>();
        for (int i = 0; i < m_lisDefs.Count; i++)
        {
            if(m_lisDefs[i].protectId == 999)
            {
                defIds.Add(m_lisDefs[i].defId);
            }
            else
            {
                protectIds.Add(m_lisDefs[i].protectId);
            }
        }
        bool protect_In_def = false;
        for (int i = 0; i < defIds.Count; i++)
        {
            if (protectIds.Contains(defIds[i]))
            {
                protect_In_def = true;
                break;
            }
        }
        if (protect_In_def)
        {
            result += string.Format("既是被打的对象 又是要去保护的对象 矛盾了");
        }
        if (!string.IsNullOrEmpty(""))
        {
            result += "\n";
        }
        return result;
    }

    public int CompareTo(Action_Attack other)
    {
        if (this.Index > other.Index)
        {
            return 1;
        }
        else if (this.Index == other.Index)
        {
            return 0;
        }
        else
        {
            return -1;
        }
    }

    protected Dmg GetDmgByEntityId(int id)
    {
        for (int i = 0; i < m_lisDefs.Count; i++)
        {
            if(m_lisDefs[i].defEntityId == id)
            {
                return m_lisDefs[i];
            }
            if(m_lisDefs[i].protectEntityId == id)
            {
                return m_lisDefs[i];
            }
        }
        return null;
    }
}

//此类的产生原因 编辑器序列化的时候有问题
//为了实现保护...
public class Action_Attack_Empty : Action_Attack
{
    //攻击实体
    [HideInInspector]
    protected BattleEntityHero attacker;
    //受击实体
    [HideInInspector]
    protected List<BattleEntityHero> m_lisDefEntitys;
    //用来检测回合有没有结束
    [HideInInspector]
    protected Dictionary<int, bool> m_DicEntityActionFinish;
    //去保护的实体
    protected List<BattleEntityHero> m_lisProtectEntitys;
    protected Dictionary<int, int> m_DicProtectEntityStep;
    protected int attackerInDefs = 0;

    public override void EnterNode()
    {
        base.EnterNode();
        m_DicEntityActionFinish = new Dictionary<int, bool>();
        attacker = BattleEntityFactory.Instance.GetBtEntity(this.attackEntityId) as BattleEntityHero;
        m_lisDefEntitys = new List<BattleEntityHero>();
        m_lisProtectEntitys = new List<BattleEntityHero>();
        m_DicProtectEntityStep = new Dictionary<int, int>();
        m_DicEntityActionFinish.Add(attacker.Id, false);
        for (int i = 0; i < m_lisDefs.Count; i++)
        {
            //如果有保护那么防御 防御对象就换成保护的人
            if (m_lisDefs[i].protectEntityId != 0)
            {
                m_lisProtectEntitys.Add(BattleEntityFactory.Instance.GetBtEntity(m_lisDefs[i].protectEntityId) as BattleEntityHero);
                m_DicProtectEntityStep.Add(m_lisDefs[i].protectEntityId, 0);
                m_DicEntityActionFinish.Add(m_lisDefs[i].protectEntityId, false);
            }
            else
            {
                if(!m_DicEntityActionFinish.ContainsKey(m_lisDefs[i].defEntityId))
                    m_DicEntityActionFinish.Add(m_lisDefs[i].defEntityId, false);
            }
            m_lisDefEntitys.Add(BattleEntityFactory.Instance.GetBtEntity(m_lisDefs[i].defEntityId) as BattleEntityHero);
            if (m_lisDefEntitys.Contains(attacker))
            {
                attackerInDefs = 1;
            }
        }
    }

    //是否是防御方ID
    protected bool IsDefId(int defEntityId)
    {
        for (int i = 0; i < m_lisDefEntitys.Count; i++)
        {
            if (m_lisDefEntitys[i].Id == defEntityId)
            {
                return true;
            }
        }
        return false;
    }

    //是否是保护方ID
    protected bool IsProtectId(int id)
    {
        for (int i = 0; i < m_lisProtectEntitys.Count; i++)
        {
            if (m_lisProtectEntitys[i].Id == id)
            {
                return true;
            }
        }
        return false;
    }

    //所有的实体对象是否行动完毕
    protected bool CheckAllEntityActionFinish()
    {
        foreach (var item in m_DicEntityActionFinish.Values)
        {
            if (!item)
            {
                return false;
            }
        }
        return true;
    }

    //获取保护实体
    protected BattleEntityHero GetProtectEntityById(int entityId)
    {
        for (int i = 0; i < m_lisProtectEntitys.Count; i++)
        {
            if (m_lisProtectEntitys[i].Id == entityId)
            {
                return m_lisProtectEntitys[i];
            }
        }

        return null;
    }


    protected virtual void DoProtect(BattleEntityHero protecter,Vector3 sPos,Vector3 tPos,float t)
    {
        if (t <= 0)
            t = 0.01f;

        m_DicProtectEntityStep[protecter.Id] = 1;
        if (t > HeroFightDef.c_fProtectMinMoveTime)
        {
            //延迟处理
            HeroBattleMgr.Instance.AddTimer(delegate () 
            {
                float speed = Vector3.Distance(tPos, sPos) / HeroFightDef.c_fProtectMinMoveTime;
                protecter.ChangeState(BattleHeroState.c_sMState_Move, MoveComp.moveType.Uniform,
                       HeroFightDef.c_sAction_Run, true, speed, tPos);

            }, t - HeroFightDef.c_fProtectMinMoveTime);
        }
        else
        {
            float speed = Vector3.Distance(tPos, sPos) / t;
            protecter.ChangeState(BattleHeroState.c_sMState_Move, MoveComp.moveType.Uniform,
                   HeroFightDef.c_sAction_Run, true, speed, tPos);
        }
    }
}

public class Action_Attack_Slash : Action_Attack_Empty
{
    public Action_Attack_Slash() { }
    public Action_Attack_Slash(Action_Attack parent)
    {
        NodeId = parent.NodeId;
        Index = parent.Index;
        isWorking = parent.isWorking;
        attackId = parent.attackId;
        attackEntityId = parent.attackEntityId;
        m_lisDefs = parent.m_lisDefs;
        skillActionId = parent.skillActionId;
        sActionConfig = parent.sActionConfig;
        m_bComeBack = parent.m_bComeBack;
        m_bCounter = parent.m_bCounter;
    }
    // 0 未进入  1 攻击方跑过去  2 攻击方挥砍  3 攻击动作结束
    private int step = 0;

    public override void EnterNode()
    {
        base.EnterNode();
        step = 0;

        m_lisDefEntitys.Sort((x, y) =>
        {
            int result = 0;
            //左侧
            if (x.m_pHeroVo.index > y.m_pHeroVo.index)
            {
                result = x.m_pHeroVo.m_bFilp ? 1 : -1;
            }
            else if(x.m_pHeroVo.index == y.m_pHeroVo.index)
            {
                result = 0;
            }
            else
            {
                result = x.m_pHeroVo.m_bFilp ? -1 : 1;
            }
            return result;
        });
        int tIndex = m_lisDefEntitys[0].m_pHeroVo.index;
        Vector3 dir = HeroFightUtil.GetDir(attacker.m_pHeroVo.index, tIndex);
        Vector3 pos = HeroFightUtil.GetHeroPosByIndex(tIndex);
        if (Vector3.Distance(pos, attacker.m_pGameObj.transform.position) > sActionConfig.attackRange)
        {
            step = 1;
            pos -= dir * sActionConfig.attackRange;
            attacker.ChangeState(BattleHeroState.c_sMState_Move, MoveComp.moveType.Acceleration,
                                sActionConfig.action2, true, dir, pos);
        }
        else
        {
            Attack();
        }
    }
    public override void OnHandMessage(MessageBody msg)
    {
        if(msg.msgId == MessageId.Arrive)
        {
            if(step == 1 && msg.senderId == attacker.Id)
            {
                //攻击方跑到了 被攻击方面前
                Attack();
            }
            //攻击者 回到原地
            if(step == 3 && attacker.Id == msg.senderId)
            {
                attacker.ChangeState(BattleHeroState.c_sMState_Idle);
                attacker.InitRenderDir();
                m_DicEntityActionFinish[attacker.Id] = true;
                CheckFinish();
            }
            //
            if (m_lisDefEntitys[0].Id == msg.senderId)
            {
                m_lisDefEntitys[0].ChangeState(BattleHeroState.c_sMState_Idle);
                m_lisDefEntitys[0].InitRenderDir();
                m_DicEntityActionFinish[m_lisDefEntitys[0].Id] = true;
                CheckFinish();
            }
            //保护者走到了 要保护的人面前
            if (IsProtectId(msg.senderId) && m_DicProtectEntityStep[msg.senderId] == 1)
            {
                m_DicProtectEntityStep[msg.senderId] = 2;
                BattleEntityHero protecter = BattleEntityFactory.Instance.GetBtEntity(msg.senderId) as BattleEntityHero;
                protecter.ChangeState(BattleHeroState.c_sMState_Hit,HeroFightDef.c_iHitType_Dmg ,GetDmgByEntityId(protecter.Id),true);
                return;
            }
            if(IsProtectId(msg.senderId) && m_DicProtectEntityStep[msg.senderId] == 2)
            {
                m_DicProtectEntityStep[msg.senderId] = 3;
                BattleEntityHero protecter = BattleEntityFactory.Instance.GetBtEntity(msg.senderId) as BattleEntityHero;
                protecter.ChangeState(BattleHeroState.c_sMState_Idle);
                protecter.InitRenderDir();
                m_DicEntityActionFinish[protecter.Id] = true;
                CheckFinish();
            }
        }
        if(msg.msgId == sActionConfig.action3 && msg.senderId == attacker.Id)
        {
            //攻击方 攻击动作结束
            step = 3;
            bool attackerBackHome = m_bComeBack && !attacker.IsInInitPos();
            if (attackerBackHome)
            {
                attacker.BackInitPos(sActionConfig.action2);
            }
            else
            {
                attacker.InitRenderDir();
                attacker.ChangeState(BattleHeroState.c_sMState_Idle);
                m_DicEntityActionFinish[attacker.Id] = true;
                CheckFinish();
            }
        }
        if(msg.msgId == HeroFightDef.c_sAction_Hit && IsDefId(msg.senderId))
        {
            if (msg.senderId == m_lisDefEntitys[0].Id)
            {
                //受击方 受击动作结束
                bool defBackHome = !m_lisDefEntitys[0].IsInInitPos() && m_bCounter;
                if (defBackHome)
                {
                    m_lisDefEntitys[0].BackInitPos();
                }
                else
                {
                    m_lisDefEntitys[0].ChangeState(BattleHeroState.c_sMState_Idle);
                    m_DicEntityActionFinish[m_lisDefEntitys[0].Id] = true;
                    CheckFinish();
                }
            }
            else
            {
                m_DicEntityActionFinish[msg.senderId] = true;
                CheckFinish();
            }
        }
        if(msg.msgId == HeroFightDef.c_sAction_Dead && IsDefId(msg.senderId))
        {
            //受击方 死亡动作结束
            m_DicEntityActionFinish[msg.senderId] = true;
            CheckFinish();
        }
        if(msg.msgId == HeroFightDef.c_sAction_Hit && IsProtectId(msg.senderId))
        {
            //保护者回去
            BattleEntityHero protecter = BattleEntityFactory.Instance.GetBtEntity(msg.senderId) as BattleEntityHero;
            protecter.BackInitPos();
        }
        if(msg.msgId == HeroFightDef.c_sAction_Dead && IsProtectId(msg.senderId))
        {
            //保护者死亡
            m_DicEntityActionFinish[msg.senderId] = true;
            CheckFinish();
        }
    }
    private void Attack()
    {
        step = 2;
        //直接攻击
        attacker.ChangeState(BattleHeroState.c_sMState_Action, sActionConfig.action3, false);
        for (int i = 0; i < m_lisDefEntitys.Count; i++)
        {
            int defIndex = i;
            Dmg dmg = GetDmgByEntityId(m_lisDefEntitys[defIndex].Id);
            BattleEntityHero beProtecter = m_lisDefEntitys[defIndex];
            if (dmg.protectEntityId == 0)
            {
                //没有保护者, 直接受击
                HeroBattleMgr.Instance.AddTimer(delegate () 
                {
                    beProtecter.ChangeState(BattleHeroState.c_sMState_Hit, HeroFightDef.c_iHitType_Dmg,GetDmgByEntityId(beProtecter.Id),true);
                }, sActionConfig.hitDelay,"普通攻击");
            }
            else
            {
                BattleEntityHero Protecter = GetProtectEntityById(dmg.protectEntityId);
                Vector3 tPos = beProtecter.m_pGameObj.transform.position;
                Vector3 sPos = Protecter.m_pGameObj.transform.position;
                base.DoProtect(Protecter, sPos, tPos, sActionConfig.hitDelay);
            }
        }
        #region close
        ////保护者要跑过去
        //stepProtecter = 1;
        //for (int i = 0; i < m_lisProtectEntitys.Count; i++)
        //{
        //    Dmg dmg = GetDmgByEntityId(m_lisProtectEntitys[i].Id);
        //    BattleEntityHero beProtecter = BattleEntityFactory.Instance.GetBtEntity(dmg.defEntityId) as BattleEntityHero;
        //    Vector3 tPos = beProtecter.m_pGameObj.transform.position;
        //    Vector3 sPos = m_lisProtectEntitys[i].m_pGameObj.transform.position;
        //    // 距离 / 挥刀起到打到人的时间
        //    if(sActionConfig.hitDelay > HeroFightDef.c_fProtectMinMoveTime)
        //    {
        //        //时间过长
        //        int protectIndex = i;
        //        HeroBattleMgr.Instance.AddTimer(delegate () 
        //        {
        //            sPos = m_lisProtectEntitys[protectIndex].m_pGameObj.transform.position;
        //            float speed = Vector3.Distance(tPos, sPos) / HeroFightDef.c_fProtectMinMoveTime;
        //            m_lisProtectEntitys[protectIndex].ChangeState(BattleHeroState.c_sMState_Move, MoveComp.moveType.Uniform,
        //                   HeroFightDef.c_sAction_Run, true, speed, tPos);

        //        }, sActionConfig.hitDelay - HeroFightDef.c_fProtectMinMoveTime);
        //    }
        //    else
        //    {
        //        float speed = Vector3.Distance(tPos, sPos) / sActionConfig.hitDelay;
        //        m_lisProtectEntitys[i].ChangeState(BattleHeroState.c_sMState_Move, MoveComp.moveType.Uniform,
        //               HeroFightDef.c_sAction_Run, true, speed, tPos);
        //    }
        //}
        #endregion
    }
    private bool CheckFinish()
    {
        bool result = CheckAllEntityActionFinish();
        if (result)
        {
            float restTime = m_bComeBack ? HeroFightDef.c_fRoundRest : 0;
            HeroBattleMgr.Instance.AddTimer(delegate ()
            {
                HeroBattleMgr.Instance.ActionFinish(this);
            }, restTime);
        }
        return result;
    }
}
public class Action_Attack_Remote: Action_Attack_Empty
{
    //# 表现上有问题，什么时候结束这一回合？ 1.子弹都到达目标? 2.目标的受击动画都播放完毕？ 3.受击特效都播放完毕?
    //# 选2
    public Action_Attack_Remote() { }
    public Action_Attack_Remote(Action_Attack parent)
    {
        NodeId = parent.NodeId;
        Index = parent.Index;
        isWorking = parent.isWorking;
        attackId = parent.attackId;
        attackEntityId = parent.attackEntityId;
        m_lisDefs = parent.m_lisDefs;
        skillActionId = parent.skillActionId;
        sActionConfig = parent.sActionConfig;
        m_bComeBack = parent.m_bComeBack;
        m_bCounter = parent.m_bCounter;
    }

    public override void EnterNode()
    {
        base.EnterNode();
        HeroEff effConfig = ConfigManager.Instance.heroEffLoader.GetInfoById(sActionConfig.action3EffId);
        for (int i = 0; i < m_lisDefEntitys.Count; i++)
        {
            int defIndex = i;
            Dmg dmg = GetDmgByEntityId(m_lisDefEntitys[defIndex].Id);
            BattleEntityHero beProtecter = m_lisDefEntitys[defIndex];

            HeroBattleMgr.Instance.AddTimer(delegate ()
            {
                BattleEntityBullet bulletEntity = BattleEntityFactory.Instance.CreateBtEntity<BattleEntityBullet>();
                bulletEntity.OnCreate(beProtecter.m_pGameObj.transform.position + effConfig.offset,
                                            sActionConfig,
                                            attacker.m_pGameObj.transform.position + effConfig.offset,
                                            Vector3.zero,
                                            dmg);
                attacker.InsertChild(bulletEntity.Id);
                bulletEntity.SetParent(attacker);

                if(dmg.protectEntityId != 0)
                {
                    BattleEntityHero protecter = GetProtectEntityById(dmg.protectEntityId);
                    Vector3 tPos = beProtecter.m_pGameObj.transform.position;
                    Vector3 sPos = protecter.m_pGameObj.transform.position;
                    float hitDelay = bulletEntity.m_pMoveComp.GetRemainingTime();
                    base.DoProtect(protecter, sPos, tPos, hitDelay);
                }

            }, effConfig.delay, "放子弹动作");
        }
        attacker.ChangeState(BattleHeroState.c_sMState_Action, sActionConfig.action2, false);
    }

    public override void OnHandMessage(MessageBody msg)
    {
        //被反击的目标跑到的原点
        if (msg.msgId == MessageId.Arrive && IsDefId(msg.senderId))
        {
            BattleEntityHero defEntity = BattleEntityFactory.Instance.GetBtEntity(msg.senderId) as BattleEntityHero;
            defEntity.ChangeState(BattleHeroState.c_sMState_Idle);
            defEntity.InitRenderDir();
            m_DicEntityActionFinish[defEntity.Id] = true;
            CheckFinish();
        }
        if(msg.msgId == MessageId.Arrive && IsProtectId(msg.senderId) && m_DicProtectEntityStep[msg.senderId] == 2)
        {
            //保护者走回去了
            m_DicProtectEntityStep[msg.senderId] = 3;
            BattleEntityHero protecter = BattleEntityFactory.Instance.GetBtEntity(msg.senderId) as BattleEntityHero;
            protecter.ChangeState(BattleHeroState.c_sMState_Idle);
            protecter.InitRenderDir();
            m_DicEntityActionFinish[protecter.Id] = true;
            CheckFinish();
        }

        //射子弹动作做完
        if (msg.msgId == sActionConfig.action2 && msg.senderId == attacker.Id)
        {
            //Debug.LogFormat("射子弹动作结束  {0}",msg.msgId);
            attacker.ChangeState(BattleHeroState.c_sMState_Idle);
            m_DicEntityActionFinish[attacker.Id] = true;
            CheckFinish();
        }

        //子弹射到了对方
        if (msg.msgId == MessageId.BulletArrive && msg.senderId == attacker.Id)
        {
            Dmg dmg = msg.args[0] as Dmg;
            if(dmg.protectEntityId == 0)
            {
                BattleEntityHero defEntity = BattleEntityFactory.Instance.GetBtEntity(dmg.defEntityId) as BattleEntityHero;
                defEntity.ChangeState(BattleHeroState.c_sMState_Hit, HeroFightDef.c_iHitType_Dmg, dmg,true);
            }
            else
            {
                BattleEntityHero protecter = GetProtectEntityById(dmg.protectEntityId);
                if (protecter != null)
                {
                    protecter.ChangeState(BattleHeroState.c_sMState_Hit, HeroFightDef.c_iHitType_Dmg, dmg,true);
                    m_DicProtectEntityStep[protecter.Id] = 2;
                }
            }
        }
        //对方受击动作做完
        if (msg.msgId == HeroFightDef.c_sAction_Hit && IsDefId(msg.senderId))
        {
            BattleEntityHero defEntity = BattleEntityFactory.Instance.GetBtEntity(msg.senderId) as BattleEntityHero;
            bool defBackHome = !defEntity.IsInInitPos() && m_bCounter;
            if (defBackHome)
            {
                defEntity.BackInitPos();
            }
            else
            {
                m_DicEntityActionFinish[defEntity.Id] = true;
                CheckFinish();
            }
        }
        //对方死亡动作做完
        if(msg.msgId == HeroFightDef.c_sAction_Dead && IsDefId(msg.senderId))
        {
            m_DicEntityActionFinish[msg.senderId] = true;
            CheckFinish();
        }

        if (msg.msgId == HeroFightDef.c_sAction_Hit && IsProtectId(msg.senderId))
        {
            //保护者回去
            BattleEntityHero protecter = BattleEntityFactory.Instance.GetBtEntity(msg.senderId) as BattleEntityHero;
            protecter.BackInitPos();
        }
        if (msg.msgId == HeroFightDef.c_sAction_Dead && IsProtectId(msg.senderId))
        {
            //保护者死亡
            m_DicEntityActionFinish[msg.senderId] = true;
            CheckFinish();
        }

    }

    private bool CheckFinish()
    {
        bool result = CheckAllEntityActionFinish();
        if (result)
        {
            float restTime = m_bComeBack ? HeroFightDef.c_fRoundRest : 0;
            HeroBattleMgr.Instance.AddTimer(delegate ()
            {
                HeroBattleMgr.Instance.ActionFinish(this);
            }, restTime);
        }
        return result;
    }
}
public class Action_Attack_Skill : Action_Attack_Empty
{
    public Action_Attack_Skill() { }
    public Action_Attack_Skill(Action_Attack parent)
    {
        NodeId = parent.NodeId;
        Index = parent.Index;
        isWorking = parent.isWorking;
        attackId = parent.attackId;
        attackEntityId = parent.attackEntityId;
        m_lisDefs = parent.m_lisDefs;
        skillActionId = parent.skillActionId;
        sActionConfig = parent.sActionConfig;
        m_bComeBack = parent.m_bComeBack;
        m_bCounter = parent.m_bCounter;
    }
    
    public override void EnterNode()
    {
        base.EnterNode();

        HeroEff effConfig = ConfigManager.Instance.heroEffLoader.GetInfoById(sActionConfig.action3EffId);
        for (int i = 0; i < m_lisDefEntitys.Count; i++)
        {
            int defIndex = i;
            Dmg dmg = GetDmgByEntityId(m_lisDefEntitys[defIndex].Id);
            BattleEntityHero defEntity = m_lisDefEntitys[defIndex];
            if(dmg.protectEntityId == 0)
            {
                //没有保护者
                HeroBattleMgr.Instance.AddTimer(delegate () 
                {
                    BattleEffectMgr.Instance.CreateEffectObj(effConfig.id, defEntity.Id,
                    defEntity.m_pGameObj.transform.position + effConfig.offset);
                    //todo  addHp
                    if (dmg.dmg >= 0)
                    {
                        float t = effConfig.lifeTime;
                        if(t<=0 || t > 3)
                        {
                            t = 3;
                        }
                        //HeroBattleMgr.Instance.AddTimer(delegate() 
                        //{
                        //    EntityMessageDispatcher.Instance.SendEntity2Node(HeroFightDef.c_sAction_Hit, defEntity.Id);
                        //},t,"增益技能BUF");
                        defEntity.ChangeState(BattleHeroState.c_sMState_Hit, HeroFightDef.c_iHitType_Dmg, dmg, false, t);
                    }
                    else
                    {
                        defEntity.ChangeState(BattleHeroState.c_sMState_Hit, HeroFightDef.c_iHitType_Dmg, dmg,true);
                    }
                }, effConfig.delay,"释放技能");
            }
            else
            {
                //有保护者
                BattleEntityHero protecter = GetProtectEntityById(dmg.protectEntityId);
                Vector3 tPos = defEntity.m_pGameObj.transform.position;
                Vector3 sPos = protecter.m_pGameObj.transform.position;
                base.DoProtect(protecter, sPos, tPos, effConfig.delay);
                HeroBattleMgr.Instance.AddTimer(delegate ()
                {
                    BattleEffectMgr.Instance.CreateEffectObj(effConfig.id, protecter.Id,
                    protecter.m_pGameObj.transform.position + effConfig.offset);
                    protecter.ChangeState(BattleHeroState.c_sMState_Hit, HeroFightDef.c_iHitType_Dmg, dmg,true);
                    m_DicProtectEntityStep[protecter.Id] = 2;
                }, effConfig.delay);
            }
        }
        attacker.ChangeState(BattleHeroState.c_sMState_Action, sActionConfig.action2, false);
    }
    public override void OnHandMessage(MessageBody msg)
    {
        //攻击者攻击动作做完
        if(msg.msgId == sActionConfig.action2 && msg.senderId == attacker.Id)
        {
            attacker.ChangeState(BattleHeroState.c_sMState_Idle);
            m_DicEntityActionFinish[attacker.Id] = true;
            CheckFinish();
        }
        if(msg.msgId == HeroFightDef.c_sAction_Hit && IsDefId(msg.senderId))
        {
            //需不需要跑回去
            BattleEntityHero defEntity = BattleEntityFactory.Instance.GetBtEntity(msg.senderId) as BattleEntityHero;
            bool defBackHome = !defEntity.IsInInitPos() && m_bCounter;
            if (defBackHome)
            {
                defEntity.BackInitPos();
            }
            else
            {
                defEntity.ChangeState(BattleHeroState.c_sMState_Idle);
                m_DicEntityActionFinish[msg.senderId] = true;
                CheckFinish();
            }
        }
        if(msg.msgId == HeroFightDef.c_sAction_Dead && IsDefId(msg.senderId))
        {
            m_DicEntityActionFinish[msg.senderId] = true;
            CheckFinish();
        }
        if(msg.msgId == MessageId.Arrive && IsDefId(msg.senderId))
        {
            BattleEntityHero defEntity = BattleEntityFactory.Instance.GetBtEntity(msg.senderId) as BattleEntityHero;
            defEntity.ChangeState(BattleHeroState.c_sMState_Idle);
            defEntity.InitRenderDir();
            m_DicEntityActionFinish[msg.senderId] = true;
            CheckFinish();
        }
        if(msg.msgId == MessageId.Arrive && IsProtectId(msg.senderId))
        {
            if (m_DicProtectEntityStep[msg.senderId] == 2)
            {
                m_DicProtectEntityStep[msg.senderId] = 3;
                BattleEntityHero protecter = BattleEntityFactory.Instance.GetBtEntity(msg.senderId) as BattleEntityHero;
                protecter.ChangeState(BattleHeroState.c_sMState_Idle);
                protecter.InitRenderDir();
                m_DicEntityActionFinish[protecter.Id] = true;
                CheckFinish();
            }
        }
        if (msg.msgId == HeroFightDef.c_sAction_Hit && IsProtectId(msg.senderId))
        {
            //保护者回去
            BattleEntityHero protecter = BattleEntityFactory.Instance.GetBtEntity(msg.senderId) as BattleEntityHero;
            protecter.BackInitPos();
        }
        if (msg.msgId == HeroFightDef.c_sAction_Dead && IsProtectId(msg.senderId))
        {
            //保护者死亡
            m_DicEntityActionFinish[msg.senderId] = true;
            CheckFinish();
        }
    }

    private bool CheckFinish()
    {
        bool result = CheckAllEntityActionFinish();
        if (result)
        {
            float restTime = m_bComeBack ? HeroFightDef.c_fRoundRest : 0;
            HeroBattleMgr.Instance.AddTimer(delegate ()
            {
                HeroBattleMgr.Instance.ActionFinish(this);
            }, restTime);
        }
        return result;
    }
}

[System.Serializable]
public class Action_Sing : ActionNode, IComparable<Action_Sing>
{
    public int skillActionId;//普攻也是技能
    [HideInInspector]
    public SkillAction sActionConfig;
    

    public override void Init()
    {
        NodeId = Index;
        sActionConfig = ConfigManager.Instance.skillActionLoader.GetInfoById(skillActionId);
    }
    public override void EnterNode()
    {
        Debug.Log("-----------------------开始淫唱-------------------------------");

        base.EnterNode();
        BattleEntityHero attacker = BattleEntityFactory.Instance.GetBtEntity(this.attackEntityId) as BattleEntityHero;

        attacker.ChangeState(BattleHeroState.c_sMState_Action, sActionConfig.action1, false);
        HeroEff config = ConfigManager.Instance.heroEffLoader.GetInfoById(sActionConfig.action1EffId);
        if (config != null)
        {
            BattleEffectMgr.Instance.CreateEffectObj(config.id, attacker.Id, attacker.m_pGameObj.transform.position + config.offset);
        }
    }
    public override void OnHandMessage(MessageBody msg)
    {
        BattleEntityHero attacker = BattleEntityFactory.Instance.GetBtEntity(this.attackEntityId) as BattleEntityHero;
        if (msg.msgId == sActionConfig.action1 && msg.senderId == attacker.Id)
        {
            attacker.ChangeState(BattleHeroState.c_sMState_Idle);
            HeroBattleMgr.Instance.AddTimer(delegate ()
            {
                HeroBattleMgr.Instance.ActionFinish(this);
            }, HeroFightDef.c_fRoundRest);
        }
    }
    public override bool NodeError()
    {
        if (BattleEntityFactory.Instance.GetBtEntity(this.attackEntityId) == null)
        {
            Debug.LogFormat("{0} 说唱节点  attackId:{1} 没有找到", Index, this.attackEntityId);
            return true;
        }

        if (skillActionId == 0)
        {
            Debug.LogFormat("{0} 说唱节点  skillActionId:{1} 不能为0", Index, this.skillActionId);
            return true;
        }

        return false;
    }

    public override string EditorNodeError()
    {
        string result = "";
        if (skillActionId == 0)
        {
            result += string.Format("{0} 说唱节点  skillActionId:{1} 不能为0 \n", Index, this.skillActionId);
        }
        return result;
    }

    public int CompareTo(Action_Sing other)
    {
        if (this.Index > other.Index)
        {
            return 1;
        }
        else if (this.Index == other.Index)
        {
            return 0;
        }
        else
        {
            return -1;
        }
    }
}

[System.Serializable]
public class Action_DoBuffer : ActionNode, IComparable<Action_DoBuffer>
{
    //BUF 回合的结束

    //Buf 里的 attackerID是自己
    public List<BufDmg> lisBufDmg = new List<BufDmg>();

    public override void Init()
    {
        for (int i = 0; i < lisBufDmg.Count; i++)
        {
            lisBufDmg[i].bufConfig = ConfigManager.Instance.SkillEffectLoader.GetInfoById(lisBufDmg[i].bufId);
        }
    }

    public override void EnterNode()
    {
        base.EnterNode();
        BattleEntityHero attacker = BattleEntityFactory.Instance.GetBtEntity(this.attackEntityId) as BattleEntityHero;
        //attacker.StartActionNode(this);

        for (int i = 0; i < lisBufDmg.Count; i++)
        {
            if(lisBufDmg[i].bufConfig != null)
            {
                BattleEffectMgr.Instance.CreateEffectObj(lisBufDmg[i].bufConfig.heroBatEffectId, attacker.m_pGameObj.transform.position);
                //todo  addHp  or subHp
                attacker.ChangeState(BattleHeroState.c_sMState_Hit, HeroFightDef.c_iHitType_BufDmg, lisBufDmg[i], false, HeroFightDef.c_fBufCheck);
            }
        }

        HeroBattleMgr.Instance.AddTimer(delegate ()
        {
            HeroBattleMgr.Instance.ActionFinish(this);
        }, HeroFightDef.c_fBufRest);
    }

    public override bool NodeError()
    {
        if (lisBufDmg.Count <= 0)
        {
            Debug.LogFormat("{0} buf结算节点  没有具体结算Buf信息 ", this.Index);
            return true;
        }

        for (int i = 0; i < lisBufDmg.Count; i++)
        {
            if(lisBufDmg[i].bufConfig == null)
            {
                Debug.LogFormat("{0} buf节点 里的bufId {1}没有找到配置",Index,lisBufDmg[i].bufId);
            }
        }
        return false;
    }

    public override string EditorNodeError()
    {
        string result = "";
        if (lisBufDmg.Count <= 0)
        {
            result = string.Format("{0} buf结算节点  没有具体结算Buf信息 \n", this.Index);
        }
        return result;
    }

    public int CompareTo(Action_DoBuffer other)
    {
        if (this.Index > other.Index)
        {
            return 1;
        }
        else if (this.Index == other.Index)
        {
            return 0;
        }
        else
        {
            return -1;
        }
    }
}

//最基础的ActionNode
[System.Serializable]
public class ActionNode : IComparable<ActionNode>
{
    [HideInInspector]
    public int NodeId;              //节点的唯一ID，和index保持一致就好了
    public int Index;               //行为节点 索引
    [HideInInspector]
    public bool isWorking;
    public int attackId;            //攻击执行者 位置索引
    [HideInInspector]
    public int attackEntityId;


    //实体都创建好了后调用,初始化实体ID
    public virtual void ConvertEntityId()
    {
        attackEntityId = HeroBattleMgr.Instance.ConvertReportId2EntityId(attackId);
    }

    public virtual void Init()
    {

    }

    public virtual void EnterNode()
    {
        isWorking = true;
    }
    public virtual void ExitNode()
    {
        isWorking = false;
    }
    public virtual bool NodeError()
    {
        return false;
    }

    public virtual string EditorNodeError()
    {
        string result = "";

        return result;
    }

    public virtual int CompareTo(ActionNode other)
    {
        if (this.Index > other.Index)
        {
            return 1;
        }
        else if (this.Index == other.Index)
        {
            return 0;
        }
        else
        {
            return -1;
        }
    }

    public virtual void OnHandMessage(MessageBody msg)
    {

    }
}

[System.Serializable]
public class Dmg
{
    public int defId;               //防御方 位置索引
    [HideInInspector]
    public int defEntityId;         
    public int dmg;                 //伤害数值
    public bool isCri;              //是否是暴击伤害
    public int protectId=999;           //保护这个受伤对象
    [HideInInspector]
    public int protectEntityId;
    //这个伤害是否是免伤
    public bool isGod = false;
    //技能会打出 BUF
    public List<BufData> bufs = new List<BufData>();
    //反击节点，编辑器有用
    [HideInInspector]
    public int counterNodeId;
}

[System.Serializable]
public class BufData
{
    public int bufId;               //SkillEffId
    public int lifeTime;            //持续回合数
}

[System.Serializable]
public class BufDmg
{
    public int dmg;                 //伤害值
    public int bufId;               //SkillEffId
    [HideInInspector]
    public SkillEffect bufConfig;   //配置
}

